// @(#)dispatch.cc
// Time-stamp: <2008-12-23 12:39:40 lancer>
// Copyright 2008 Julian Qian
// Author: root@localhost.localdomain
// Version: $Id: dispatch.cc,v 0.0 2008/11/17 17:13:59 root Exp $
// Keywords: 

#include <sys/signal.h>
#include <sys/time.h>

#include "common.hh"
#include "dispatch.hh"
#include "log.hh"

Dispatch* Dispatch::_theDispatch = NULL;

Dispatch*
Dispatch::theDispatch(){
    if(NULL == _theDispatch){
        _theDispatch = new Dispatch();
    }
    
    return _theDispatch;
}

Dispatch::Dispatch(){
    
}

Dispatch::~Dispatch(){
    delete _theDispatch;
}

void
Dispatch::engine(Sigfunc func, int delay = 5){
	int res = 0;

	Signal(SIGALRM, func);
	
	struct itimerval tick;
	memset(&tick, 0, sizeof(tick));

	// Timeout to run function first time
	tick.it_value.tv_sec = delay;
	tick.it_value.tv_usec = 0;
	
	// Interval time to run function
	tick.it_interval.tv_sec = delay; // sec
	tick.it_interval.tv_usec = 0; // micro sec
	// Set timer, ITIMER_REAL : real-time to decrease timer, send SIGALRM when timeout
	res = setitimer(ITIMER_REAL, &tick, NULL);
	if(res){
		LFatal( "Set timer failed!!" );
	}

	while(1){
		pause();
	}
	// pthread_exit(0);
}

Sigfunc
Dispatch::signal(int signo, Sigfunc func){
	struct sigaction act, oact;

	act.sa_handler = func;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if (signo == SIGALRM) {
#ifdef	SA_INTERRUPT
		act.sa_flags |= SA_INTERRUPT;	/* SunOS 4.x */
#endif
	} else {
#ifdef	SA_RESTART
		act.sa_flags |= SA_RESTART;		/* SVR4, 44BSD */
#endif
	}
	if (sigaction(signo, &act, &oact) < 0)
		return(SIG_ERR);
	return(oact.sa_handler);
}

// For our signal() function
Sigfunc
Dispatch::Signal(int signo, Sigfunc func){
	Sigfunc	sigfunc;

	if ( (sigfunc = signal(signo, func)) == SIG_ERR){
        LFatal( "Signal failed!" );
    }

	return(sigfunc);
}

